package dk.aiszone.lang.autosource.generatorobjects;

import java.util.LinkedHashMap;
import java.util.Map;

import dk.aiszone.lang.autosource.generatorobjects.helpers.ImportsList;
import dk.aiszone.lang.autosource.generatorobjects.interfaces.GeneratorObject;

/**
 * Representation of an annotation in Java 5+<br>
 * The <code>Annotation</code> class supports normal annotation declaration with internal values.
 * 
 * @author ads
 */
public class Annotation extends GeneratorObject {

    private ImportsList imports;
    private final Class type;
    private Map<String, Object> values;

    /**
     * Constructor for the <code>Annotation</code> class.
     * 
     * @param type
     *            <code>Class</code> representing the annotation class.
     */
    public Annotation(Class type) {
        this(type, null, null);
    }

    /**
     * Constructor for the <code>Annotation</code> class.
     * 
     * @param type
     *            <code>Class</code> representing the annotation class.
     * @param name
     *            The name of the value to set initially.
     * @param value
     *            The value of the value to set initially.
     */
    public Annotation(Class type, String name, String value) {
        this.type = type;
        this.imports = new ImportsList();
        this.values = new LinkedHashMap<String, Object>();
    }

    /**
     * Adds an <code>Import</code> to the body.
     * 
     * @param _import
     *            <code>Import</code> needed by the body.
     */
    public void addNeededImport(Import _import) {
        imports.addImport(_import);
    }

    /**
     * Add a value to the <code>Annotation</code>.<br>
     * The value will be formatted as (<i>name</i> = <i>value</i>)
     * 
     * @param name
     *            The name of the value
     * @param value
     *            The value of the value
     */
    public void addValue(String name, Annotation value) {
        imports.addAll(value.getNeededImports());
        values.put(name, value);
    }

    /**
     * Add a value to the <code>Annotation</code>.<br>
     * The value will be formatted as (<i>name</i> = <i>value</i>).<br>
     * This method will automatically wrap the value in &quot;<i>value</i>&quot;
     * 
     * @param name
     *            The name of the value
     * @param value
     *            The value of the value
     */
    public void addStringValue(String name, String value) {
        values.put(name, "\"" + value + "\"");
    }

    /**
     * Add a value to the <code>Annotation</code>.<br>
     * The value will be formatted as (<i>name</i> = <i>value</i>)
     * 
     * @param name
     *            The name of the value
     * @param value
     *            The value of the value
     */
    public void addValue(String name, String value) {
        values.put(name, value);
    }

    /**
     * Retrieve the name of the annotation.
     * 
     * @return The annotation name.
     */
    public String getName() {
        return type.getClassName();
    }

    /**
     * Retrieve a <code>ImportList</code> containing all the <code>Imports</code> needed by the <code>Annotation</code>.
     * 
     * @return The needed <code>Imports</code>.
     */
    public ImportsList getNeededImports() {
        if (type.requiresImport()) {
            imports.addImports(type.toImports());
        }

        return imports;
    }

    /**
     * Get the type of annotation
     * 
     * @return Class representing the class type of the annotaion
     */
    public Class getType() {
        return type;
    }

    /**
     * Retrieve the values of the <code>Annotation</code>.
     * 
     * @return <code>Map</code> of <code>String</code> keys to either <code>String</code> or <code>Annotation</code> values.
     */
    public Map<String, Object> getValues() {
        return values;
    }
}